﻿
-----------------------------------------------------------------------
-- MatrixEvent.lua
--
-- A Framework for World Of Warcraft addons
-- Copyright (C) 2007  wwkkii
-- 
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- any later version.
-- 
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
-- 
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
-- 

-- Home Page: http://code.google.com/p/wowmatrix
-----------------------------------------------------------------------

local __version__ = { "MatrixEvent", 0, 1, 1 };
if (MatrixUpdateVersion(__version__)) then return; end

-------------------------------------------------------------------------------
-- local variables
-------------------------------------------------------------------------------

local event_callbacks = { };
local wow_ignores = { };

local event_table = { };
local event_queue = nil;

-------------------------------------------------------------------------------
-- local functions
-------------------------------------------------------------------------------

local function Matrix_OnDefaultEvent()
end

local function Matrix_DispatchEvent(evnm)
	local evtbl;

	evtbl = event_table[evnm];
	if (evtbl) then
		local idx, obj;
		for idx = 1, #evtbl, 1 do
			obj = evtbl[idx];
			cbname = obj.ev_callbacks[evnm];
			obj:SafeInvoke(cbname, evnm);
		end
	end
end

-------------------------------------------------------------------------------
-- MatrixMainFrame
-------------------------------------------------------------------------------

local function MatrixMainFrame_OnUpdate()
	local idx, eq;

	if (event_queue) then
		eq = event_queue;
		event_queue = nil;
		for idx = 1, #eq, 1 do
			event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 = unpack(eq[idx]);
			if (event) then
				Matrix_DispatchEvent(event);
			end
		end
	end
--	Matrix_DispatchEvent("UPDATE");
end

local function MatrixMainFrame_OnEvent()
	Matrix_DispatchEvent(event);
end

MatrixMainFrame = CreateFrame("Frame", nil, UIParent);

MatrixMainFrame:SetScript("OnUpdate", MatrixMainFrame_OnUpdate);
MatrixMainFrame:SetScript("OnEvent", MatrixMainFrame_OnEvent);

-------------------------------------------------------------------------------
-- Extend matrix Functions
-------------------------------------------------------------------------------

matrix.DefineEvent = function(evnm, cbname, wow)
	if (not matrix.IsKeyName(evnm)) then
		matrix.Crash("ERROR_BAD_NAME", "Event", evnm);
		return;
	end
	if (cbname == nil) then
		cbname = "On"..matrix.ToWord(evnm);
	end
	event_callbacks[evnm] = cbname;
	if (not wow) then
		wow_ignores[evnm] = true;
	else
		wow_ignores[evnm] = false;
	end
end

matrix.SendEvent = function(...)
	event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 = ...;
	Matrix_DispatchEvent(event);
end

matrix.PostEvent = function(...)
	if (event_queue == nil) then
		event_queue = { };
	end
	event_queue[#event_queue + 1] = { ... };
end

-------------------------------------------------------------------------------
-- MatrixEvent Interface
-------------------------------------------------------------------------------

MatrixInterface("MatrixEvent");

function MatrixEvent:RegisterEvent(evnm, cbname)
	local idx, evtbl;

	if (not matrix.IsKeyName(evnm)) then
		self:Crash("ERROR_BAD_NAME", "Event", evnm);
	end

	if (not cbname) then
		cbname = event_callbacks[evnm];
		if (not cbname) then
			cbname = "On"..matrix.ToWord(evnm);
		end
	end
	if (not self.ev_callbacks) then
		self.ev_callbacks = { };
	end
	self.ev_callbacks[evnm] = cbname;
	if (not self[cbname]) then
		self.cbname = Matrix_OnDefaultEvent;
	end
	evtbl = event_table[evnm];
	if (evtbl == nil) then
		evtbl = { };
		if (not wow_ignores[evnm]) then
			MatrixMainFrame:RegisterEvent(evnm);
		end
	else
		for idx = 1, #evtbl, 1 do
			if (evtbl[idx] == self) then
				return;
			end
		end
	end
	evtbl[#evtbl + 1] = self;
	event_table[evnm] = evtbl;
end

function MatrixEvent:UnregisterEvent(evnm)
	local idx, evtbl;

	if ((not self.ev_callbacks) or (not self.ev_callbacks[evnm])) then
		return;
	end

	evtbl = event_table[evnm];
	if (evtbl == nil) then
		return;
	end
	for idx = 1, #evtbl, 1 do
		if (evtbl[idx] == self) then
			tremove(evtbl, idx);
			self.ev_callbacks[evnm] = nil;
			if (#(evtbl) <= 0) then
				evtbl = nil;
				if (not wow_ignores[evnm]) then
					MatrixMainFrame:UnregisterEvent(evnm);
				end
			end
			event_table[evnm] = evtbl;
			return;
		end
	end
end

function MatrixEvent:UnregisterAllEvents()
	local evnm;

	if (type(self.ev_callbacks) == "table") then
		for evnm in pairs(self.ev_callbacks) do
			self:UnregisterEvent(evnm);
		end
	end
	self.ev_callbacks = nil;
end

function MatrixEvent:EnableUpdate()
end

function MatrixEvent:EnableHeartBeat()
end

function MatrixEvent:DisableHeartBeat()
end

function MatrixEvent:OnUpdate()
end

function MatrixEvent:OnHeartBeat()
end

-------------------------------------------------------------------------------
-- Initial Events
-------------------------------------------------------------------------------
matrix.DefineEvent("APPLET_CREATE");
matrix.DefineEvent("APPLET_ENABLE");
matrix.DefineEvent("APPLET_DISABLE");
